//
//  TPImageView.m
//  Pods
//
//  Created by caixun on 15/11/4.
//
//

#import "TPImageView.h"
#import "SDWebImageManager.h"
#import "UIView+WebCacheOperation.h"
#import "SDWebImageCompat.h"
#import "objc/runtime.h"


/// 是否为NSString类型（单独处理NSMutableString）
#define TP_Str_Class(str) [str isKindOfClass:[NSString class]]
#define TP_mStr_Class(mstr) [mstr isKindOfClass:[NSMutableString class]]

/// 是否有效，不为空，且是NSString类型，且count值大于0（单独处理NSMutableString）
#define TP_Str_Is_Valid(str) ((str) && (TP_Str_Class(str)) && ([str length] > 0))
#define TP_mStr_Is_Valid(mstr) ((mstr) && (TP_mStr_Class(mstr)) && ([mstr length] > 0))

/// 是否无效，或为空，或不是NSString类型，或count值小于等于0（单独处理NSMutableString）
#define TP_Str_Not_Valid(str) ((!str) || (!TP_Str_Class(str)) || ([str length] <= 0))
#define TP_mStr_Not_Valid(mstr) ((!mstr) || (!TP_mStr_Class(mstr)) || ([mstr length] <= 0))

/// 格式化字符串
#define TP_Str_Format(...) [NSString stringWithFormat:__VA_ARGS__]

/// nil保护，当为nil时，返回@""，避免一些Crash
#define TP_Str_Protect(str) ((str) ? (str) : (@""))


@implementation TPImageViewBtn


@end


@interface TPImageView ()


// 加载网络图片时是否显示渐变动画
@property (nonatomic, assign) BOOL isShowDismissAnimated;
// 动画时间
@property (nonatomic, assign) CGFloat fltAnimDuration;
// 为imageView添加一个button，实现点击事件
@property (nonatomic, strong) TPImageViewBtn *btn;
// 加载网络图片时的占位图片
@property (nonatomic, strong) UIImage *imgPlaceholder;
// 加载网络图片失败时显示的图片
@property (nonatomic, strong) UIImage *imgError;
// 是否显示占位图片
@property (nonatomic, assign) BOOL isShowPlaceholderImg;
// 占位图的显示模式
@property (nonatomic, assign) UIViewContentMode placeholderImgContentMode;
// 图片下载完成后的显示模式
@property (nonatomic, assign) UIViewContentMode commonContentMode;


@end


@implementation TPImageView


#pragma mark - *********************************** View Lifecycle **********************************

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        /// 初始化变量
        [self initVariable];
        
        /// 设置公共属性，与App的UI规范 无关
        [self setCommonAttribute];
        
        /// 设置公共属性，与App的UI规范 有关
        [self setCustomAttribute];
    }
    
    return self;
}

- (void)initVariable
{
    /// 默认不显示动画
    _isShowDismissAnimated = NO;
    
    /// 默认动画时间为0.5
    _fltAnimDuration = 0.5;
}

/// 设置公共属性，与App的UI规范 无关
- (void)setCommonAttribute
{
    if (self)
    {
        self.backgroundColor = [UIColor clearColor];
        
        self.clipsToBounds = YES;
    }
}

/// 设置公共属性，与App的UI规范 有关
- (void)setCustomAttribute
{
    if (self)
    {
        /// 下载完成后默认显示模式为拉伸放大
        _commonContentMode = UIViewContentModeScaleToFill;
        _placeholderImgContentMode = UIViewContentModeCenter;
        self.contentMode = _commonContentMode;
                
        _imgPlaceholder = [UIImage imageNamed:@""];
        
        /// 默认显示占位图片
        _isShowPlaceholderImg = YES;
    }
}

- (void)dealloc
{
    [self cancelCurrentImageLoad];
}


#pragma mark - ********************************** 初始化方法 工厂模式 *********************************

+ (instancetype)getWithFrame:(CGRect)frame
{
    TPImageView *imgv = [[self alloc] initWithFrame:frame];
    
    return imgv;
}

+ (instancetype)getWithFrame:(CGRect)frame image:(UIImage *)img
{
    TPImageView *imgv = [[self alloc] initWithFrame:frame image:img];
    
    return imgv;
}


#pragma mark - ********************************** 初始化方法 实例方法 *********************************

- (instancetype)initWithFrame:(CGRect)frame image:(UIImage *)img
{
    if (self = [self initWithFrame:frame])
    {
        [self setImage:img];
    }
    
    return self;
}

/// 添加一个点击事件
- (void)addTarget:(id)target action:(SEL)selAction
{
    if (self)
    {
        /// 打开UI交互
        self.userInteractionEnabled = YES;
        
        if (!_btn)
        {
            ///  添加一个透明的control，实现点击事件
            _btn = [[TPImageViewBtn alloc] initWithFrame:self.bounds];
            _btn.backgroundColor = [UIColor clearColor];
            [_btn addTarget:target
                     action:selAction
           forControlEvents:UIControlEventTouchUpInside];
            _btn.imgv = self;
            [self addSubview:_btn];
        }
    }
}


#pragma mark - *********************************** 设置属性 实例方法 **********************************

/// 设置圆角、边框
- (void)setCornerRadius:(CGFloat)fltCornerRadius
            borderWidth:(CGFloat)fltBorderWidth
            borderColor:(UIColor *)colorBorder
{
    if (self)
    {
        self.layer.cornerRadius = fltCornerRadius;
        self.layer.borderColor = colorBorder.CGColor;
        
        /// 根据屏幕的分辨率倍数适配边框宽度
        self.layer.borderWidth = [self scaleAdaptWidth:fltBorderWidth];
    }
}


#pragma mark - ************************************* 加载网络图片 ************************************

#pragma mark - 加载图片 delegate形式

/// 加载网络图片
- (void)setImageURL:(NSString *)strImgUrl
{
    [self setImageURL:strImgUrl options:0];
}

/// 异步下载图片
- (void)setImageURL:(NSString *)strImgUrl options:(SDWebImageOptions)options
{
    /// 移除之前下载队列
    [self cancelCurrentImageLoad];
    
    SDWebImageManager *manager = [SDWebImageManager sharedManager];
    /// 获取img的URL
    NSURL *urlImg = [self changeImageUrl:strImgUrl];
    NSString *key = [manager cacheKeyForURL:urlImg];
    
    if (key)
    {
       UIImage *img = [manager.imageCache imageFromMemoryCacheForKey:key];
        if (img)
        {
            [self setImage:img];
            return;
        }
        else
        {
            UIImage *img = [manager.imageCache imageFromDiskCacheForKey:key];
            if (img)
            {
                [self setImage:img];
                return;
            }
        }
    }
    
    /// 下载之前显示占位图片
    if (_isShowPlaceholderImg && _imgPlaceholder)
    {
        [self setImage:_imgPlaceholder];
        
        /// 设置占位图片的显示模式，使占位图片不拉伸比例居中显示
        self.contentMode = _placeholderImgContentMode;
    }
    else
    {
        [self setImage:nil];
        /// 设置占位图片的显示模式，使占位图片不拉伸比例居中显示
        self.contentMode = _placeholderImgContentMode;
    }
    
    

    
    /// 开始下载网络图片
    if (([urlImg isKindOfClass:[NSURL class]]))
    {
        SDWebImageManager *manager = [SDWebImageManager sharedManager];
        // [manager downloadWithURL:urlImg delegate:self options:0];
        
        __weak typeof(self) weakSelf = self;
        id <SDWebImageOperation> operation = [manager downloadImageWithURL:urlImg
                                                                   options:options
                                                                  progress:nil
                                                                 completed:^(UIImage *image,
                                                                             NSError *error,
                                                                             SDImageCacheType cacheType,
                                                                             BOOL finished,
                                                                             NSURL *imageURL)
          {
              if (!weakSelf) return;
              
              if (finished && !error)
              {
                  [weakSelf didFinishWithImage:image];
              }
              else if (finished && error)
              {
                  [weakSelf didFailWithError:error];
                  
              }
              else if (!finished)
              {
                  if (options & SDWebImageProgressiveDownload)
                  {
                      if (image)
                      {
                          weakSelf.image = image;
                          weakSelf.contentMode = _commonContentMode;
                          [weakSelf setNeedsLayout];
                      }
                  }
              }
          }];
        
        [self sd_setImageLoadOperation:operation forKey:@"UIImageViewAnimationImages"];
    }
}

#pragma mark - 加载图片 block形式

/// 加载网络图片、设置成功和失败block
- (void)setImageURL:(NSString *)strImgUrl
            success:(void (^)(UIImage *image))success
            failure:(void (^)(NSError *error))failure
{
    [self setImageURL:strImgUrl options:0 success:success failure:failure];
}

/// 异步下载图片
- (void)setImageURL:(NSString *)strImgUrl
            options:(SDWebImageOptions)options
            success:(void (^)(UIImage *image))success
            failure:(void (^)(NSError *error))failure
{
    if (_isShowPlaceholderImg && _imgPlaceholder)
    {
        /// 下载之前显示占位图片
        [self setImage:_imgPlaceholder];
        
        /// 设置占位图片的显示模式，使占位图片不拉伸比例居中显示
        self.contentMode = _placeholderImgContentMode;
    }
    
    /// 移除之前下载队列
    [self cancelCurrentImageLoad];
    
    /// 获取img的URL
    NSURL *urlImg = [self changeImageUrl:strImgUrl];
    
    /// 加载网络图片
    if ([urlImg isKindOfClass:[NSURL class]])
    {
        SDWebImageManager *manager = [SDWebImageManager sharedManager];
        __weak typeof(self) weakSelf = self;
        
        id <SDWebImageOperation> operation = [manager downloadImageWithURL:urlImg
                                                                   options:options
                                                                  progress:^(NSInteger receivedSize,
                                                                             NSInteger expectedSize)
          {
              
          }
             completed:^(UIImage *image,
                         NSError *error,
                         SDImageCacheType cacheType,
                         BOOL finished,
                         NSURL *imageURL)
          {
              if (!weakSelf) return;
              
              if (finished && !error)
              {
                  [weakSelf didFinishWithImage:image];
                  if (success)
                  {
                      success(image);
                  }
              }
              else if (finished && error)
              {
                  [weakSelf didFailWithError:error];
                  if (failure)
                  {
                      failure(error);
                  }
              }
              else if (!finished)
              {
                  if (options & SDWebImageProgressiveDownload)
                  {
                      if (image)
                      {
                          weakSelf.image = image;
                          weakSelf.contentMode = _commonContentMode;
                          
                          [weakSelf setNeedsLayout];
                      }
                  }
              }
          }];
        
        [self sd_setImageLoadOperation:operation forKey:@"UIImageViewAnimationImages"];
    }
}


#pragma mark - ************************************** 加载图片设置 ***********************************

/// 设置是否显示占位图片，不设置时为YES
- (void)setIsShowPlaceholderImg:(BOOL)isShowPlaceholderImg
{
    _isShowPlaceholderImg = isShowPlaceholderImg;
}

/// 设置下载网络图片时的占位图片，不设置时会在初始化时根据frame大小选择一个合适尺寸的图片(default_49_11.png/default_97_21.png)
- (void)setPlaceholderImage:(UIImage *)imgPlaceholder
{
    if (imgPlaceholder)
    {
        _imgPlaceholder = imgPlaceholder;
    }
}

/// 设置占位图的填充模式
- (void)setPlaceholderImgContentMode:(UIViewContentMode)placeholderImgContentMode
{
    _placeholderImgContentMode = placeholderImgContentMode;
}

/// 设置下载错误图片，不设置时不显示
- (void)setErrorImage:(UIImage *)imgError
{
    _imgError = imgError;
}

/* 设置下载图片完成后的图片显示模式(contentMode),设置时不要调用系统的setContentMode,
 下载完成后会使用finishContentMode*/
- (void)setCommonContentMode:(UIViewContentMode)commonContentMode
{
    _commonContentMode = commonContentMode;
    self.contentMode = commonContentMode;
}


#pragma mark - ************************************* Functions *************************************

/// 是否显示图片（有图模式）
- (BOOL)shouldShowImage
{
    // 先写死，日后如果有需求的话弄个成员变量去控制
    return YES;
}

/// 取消当前图片下载
- (void)cancelCurrentImageLoad
{
    [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"];
}

/// 将图片URL从NSString格式转换NSUrl格式
- (NSURL *)changeImageUrl:(NSString *)strImgUrl
{
    /// 无图片模式，直接返回
    if (![self shouldShowImage])
    {
        return nil;
    }
    
    /// 图片连接是为空，直接返回
    if (TP_Str_Not_Valid(strImgUrl))
    {
        return nil;
    }
    
    /// 图片链接是否正常
    if (![self tpCheckImageURL:strImgUrl])
    {
        return nil;
    }
    
    /// 对URL转码，处理URL中有汉字的情况
    strImgUrl = [strImgUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    /// 获取img的URL
    NSURL *urlImg = [NSURL URLWithString:strImgUrl];
    
    return urlImg;
}

/// 淡出动画，从有到无
- (void)animationEaseOut:(UIView *)view
{
    view.alpha = 1.0;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:_fltAnimDuration];
    view.alpha = 0.0;
    [UIView commitAnimations];
}

/// 淡入动画，从无到有
- (void)animationEaseIn:(UIView *)view
{
    view.alpha = 0.0;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:_fltAnimDuration];
    view.alpha = 1.0;
    [UIView commitAnimations];
}

- (CGFloat)scaleAdaptWidth:(CGFloat)fltWidth
{
    /// 如果宽度为0，则直接返回
    if (fltWidth == 0)
    {
        return fltWidth;
    }
    
    /// 获取屏幕的像素密度，如iPhone6Plus，一个点上有3个像素，该值为3
    CGFloat fltScale = [UIScreen mainScreen].scale;
    /// 传入的参数最小值要求为1，如果小于1，则设为1，保证像素最小值为1
    if (fltWidth < 1.0)
    {
        fltWidth = 1.0;
    }
    /// 要显示的点除以屏幕密度，为要返回的点，比实际传进来的要小
    return (fltScale > 0 ? (fltWidth / fltScale) : fltWidth);
}

- (BOOL)tpCheckImageURL:(NSString *)strImgUrl
{
    if (!([strImgUrl hasPrefix:@"http:"] || [strImgUrl hasPrefix:@"https:"])) /// 不是URL,直接返回NO
    {
        return NO;
    }
    
    /// 对URL转码，处理URL中有汉字的情况
    NSString *strCode = [strImgUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    /// 获取img的URL
    NSURL *urlImg = [NSURL URLWithString:strCode];
    
    /// 根据urlImg的path是否为空来判断是否为图片地址
    return TP_Str_Is_Valid([urlImg path]);
}


#pragma mark - **************************************** 代理 ****************************************

- (void)didFinishWithImage:(UIImage*)image
{
    /// 加入一个保护，判断是否下载完成成功
    if ((![image isKindOfClass:[UIImage class]])
        || (image.size.height <= 0))
    {
        return;
    }
    
    /// 下载图片成功，显示图片
    [self setImage:image];
    /// 下载成功后，设置显示模式，此时使用的是调用commonContentMode:方法设置的值，在外面手动调用系统方法是不起作用的
    self.contentMode = _commonContentMode;
    
    ///  是否显示消失动画
    if (self.isShowDismissAnimated)
    {
        [self animationEaseIn:self];
    }
}

- (void)didFailWithError:(NSError *)error
{
#ifdef DEBUG /// 测试模式下
    if (error.code == 404) /// 如果是404则显示提示404错误图片
    {
#warning 这块需要替换真正的404错误图片
        [self setImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"" ofType:@"jpg"]]];
    }
#endif
    
    if (!_imgError || ![_imgError isKindOfClass:[UIImage class]])
    {
        return;
    }
    
    /// 设置错误图片
    [self setImage:_imgError];
    
    ///  是否显示消失动画
    if (self.isShowDismissAnimated)
    {
        [self animationEaseIn:self];
    }
    
}


/// 布局
- (void)layoutSubviews
{
    [super layoutSubviews];
    
    /// 当self的frame改变时，改变btn的frame
    if (_btn)
    {
        _btn.frame = self.bounds;
    }
}


@end
